using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using CreamX.Framework.Game.GameEngine;

namespace CreamX.Framework.Game
{
    /// <summary>
    /// Basic 2DCamera class.   
    /// </summary>
    /// <remarks>Eventually idlike this to be changable with custom cameras implemented from this class.
    /// The Zero position of a CreamX camera is the top left of the screen</remarks>
    public class Camera2D : ISceneItem
    {
        #region Private Variables
        private Vector2 _position;
        private Vector2 _size;
        private float _zoom;
        private BoundingBox _boundingBox;
        #endregion

        public Camera2D()
        {
            _zoom = 1;
            _position = Vector2.Zero;
        }

        #region Public Methods
        public void Move(Vector2 vector)
        {
            _position += vector;
            if (CreamXGameEngine.Instance != null)
            {
                if (CreamXGameEngine.Instance.SceneManager.CurrentScene != null)
                {
                    if (ClampToTileSet)
                    {
                        //    CreamXTileSet __t = CreamXGameEngine.Instance.SceneManager.CurrentScene.TileSets[0];
                            Vector2 __s = _position + (Size / 2);
                            Vector2 __v = new Vector2(Bounds.Max.X, 
                                                        Bounds.Max.Y);

                            Vector2 __maxAllowed = new Vector2(
                                                Bounds.Max.X * Zoom,
                                                Bounds.Max.Y * Zoom) - Size;// -(CreamXGameEngine.Instance.SceneManager.CurrentScene.TileSets[0].TileDisplaySize / 2);

                            _position = Vector2.Clamp(_position, Vector2.Zero, __maxAllowed);
                           // _position.X =(float)Math.Round(_position.X);
                           // _position.Y = (float)Math.Round(_position.Y);
                    }
                    //if (CreamXGameEngine.Instance.SceneManager.CurrentScene.TileSets.Count > 0 && ClampToTileSet)
                    //{
                    //    CreamXTileSet __t = CreamXGameEngine.Instance.SceneManager.CurrentScene.TileSets[0];
                    //    Vector2 __s = _position + (Size / 2);
                    //    Vector2 __v = new Vector2(__t.TotalScreenSize.X, __t.TotalScreenSize.Y);

                    //    Vector2 __maxAllowed = __t.TotalScreenSize - Size;// -(CreamXGameEngine.Instance.SceneManager.CurrentScene.TileSets[0].TileDisplaySize / 2);

                    //    _position = Vector2.Clamp(_position, Vector2.Zero, __maxAllowed);
                    //}
                }
            }
            _boundingBox = new BoundingBox(new Vector3(Position, 0), new Vector3(Position + Size, 0));

        }
        public void SetPosition(Vector2 vector)
        {
            _position = vector;
            if (CreamXGameEngine.Instance != null)
            {
                if (CreamXGameEngine.Instance.SceneManager.CurrentScene != null)
                {
                    //if (CreamXGameEngine.Instance.SceneManager.CurrentScene.TileSets.Count > 0 && ClampToTileSet)
                    //{
                    //    CreamXTileSet __t = CreamXGameEngine.Instance.SceneManager.CurrentScene.TileSets[0];
                    //    Vector2 __s = _position + (Size / 2);
                    //    //Vector2 __v = new Vector2(__t.TotalScreenSize.X, __t.TotalScreenSize.Y);

                    //    Vector2 __maxAllowed = __t.TotalScreenSize - (Size / Zoom);// -(CreamXGameEngine.Instance.SceneManager.CurrentScene.TileSets[0].TileDisplaySize / 2);

                    //    _position = Vector2.Clamp(_position, Vector2.Zero, __maxAllowed);
                    //}
                }
            }
            _boundingBox = new BoundingBox(new Vector3(Position, 0), new Vector3(Position + Size, 0));

        }
        public void CenterOnObject(CreamXObject obj)
        {
            SetPosition(obj.Position - (Size / 2));
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Gets or sets the position of the camera  ??TOP LEFT OR MIDDLE (CURRENTLY MIDDLE)
        /// </summary>
        public Vector2 Position
        {
            get { return _position; }
        }

        /// <summary>
        /// The size of the Camera view area.
        /// </summary>
        /// <remarks>This basically sets the backbuffer width and height and sets the window to be this size
        /// It should also have a full screen item too(Still undecided as to wether to keep this as is or change)</remarks>
        public Vector2 Size
        {
            get { return _size; }
            set
            {
                _size = value;
                _boundingBox = new BoundingBox(new Vector3(Position, 0),
                    new Vector3(Position + Size, 0));
            }
        }

        /// <summary>
        /// Gets or sets the zoom value of the camera. Range 0-1
        /// </summary>
        /// <remarks>Not currently active</remarks>
        public float Zoom
        {
            get { return _zoom; }
            set
            {
                if (_zoom > 4)
                    _zoom = 4;
                else
                    _zoom = value;

                _position *= _zoom;
                if (CreamXGameEngine.Instance != null)
                    CreamXGameEngine.Instance.SceneManager.CurrentScene.RebuildQuadTree();
            }
        }


        /// <summary>
        /// Returns the bounding box of the camera, this can be used to see if an item is in the screen to draw.
        /// </summary>
        /// <returns></returns>
        public BoundingBox GetBoundingBox()
        {
            return _boundingBox;// new BoundingBox(new Vector3(Position, 0), new Vector3(Size, 0));
        }

        /// <summary>
        /// Gets the position of the passed in item based on camera position.
        /// </summary>
        ///<remarks>This may change when zoom pan and rotate are working
        ///Not even sure if this is going to be used outside CreamX Internals so could potentially hide for now</remarks>
        public Vector2 GetRenderPosition(Vector2 vector2)
        {
            Vector2 _positionOutputHolder = (vector2 * _zoom) - Position;
            return _positionOutputHolder;
        }

        /// <summary>
        /// Returns the scale based on the zoom level given an original scale
        /// </summary>
        /// <param name="scale"></param>
        /// <returns></returns>
        public float GetRenderScale(float scale)
        {
            return scale * _zoom;
        }

        public bool ClampToTileSet = false;
        public BoundingBox Bounds = new BoundingBox();
        public float Scale
        {
            get
            {
                throw new Exception("The method or operation is not implemented.");
            }
            set
            {
                throw new Exception("The method or operation is not implemented.");
            }
        }

        public bool Visible
        {
            get
            {
                throw new Exception("The method or operation is not implemented.");
            }
            set
            {
                throw new Exception("The method or operation is not implemented.");
            }
        }

        public float DisplayWidth
        {
            get { return Size.X; }
        }

        public float DisplayHeight
        {
            get { return Size.Y; }
        }

        public int Layer
        {
            get
            {
                throw new Exception("The method or operation is not implemented.");
            }
            set
            {
                throw new Exception("The method or operation is not implemented.");
            }
        }
        #endregion



    }
}
